﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "GcmpModelInterface.h"
#include "IExternalObject.h"
#include "ElementCreationOptions.h"

namespace gcmp 
{
    class ICurve2d;
    class IPolyCurve;
    class IDrawingPolyCurveEvent;

    class GCMP_MODEL_INTERFACE_EXPORT IDrawingPolyCurve : public IExternalObject
    {
        DEFINE_CAST_DERIVED(gcmp::IDrawingPolyCurve, gcmp::IExternalObject);
    public:
        /// \brief 析构函数
        virtual ~IDrawingPolyCurve();

        /// \brief 获取多段线的几何曲线。
        /// 
        /// \return 返回多段线的几何曲线指针。
        virtual const IPolyCurve* GetGeometryCurve() const = 0;

        /// \brief 设置多段线的几何曲线。
        /// 
        /// \param opPolyCurve 新的几何曲线。
        /// \return 如果设置成功返回true；否则返回false。
        virtual bool SetGeometryCurve(OwnerPtr<IPolyCurve> opPolyCurve) = 0;

        /// \brief  获取多段线所在坐标系
        /// 
        /// \return  坐标系
        virtual Coordinate3d GetCoordinate() const = 0;

        /// \brief 获得所属ModelView的ID
        ///
        /// \return ElementId 所属Element
        virtual const ElementId GetModelViewId() const = 0;

        /// \brief 获得图形样式Id
        ///
        /// \return ElementId 多段线图形样式Id
        virtual ElementId GetGraphicsStyleId() const = 0;

        /// \brief 设置图形样式Id
        ///
        /// \param styleId 图形样式Id
        /// \return true 表示设置成功， false 表示设置失败
        virtual bool SetGraphicsStyleId(const ElementId& styleId) = 0;

        /// \brief 在多段线首位置添加曲线
        /// 
        /// \param opCurve    二维曲线，非闭合并且与多段线首段曲线相连，否则添加失败
        /// \return  成功添加返回True，否则返回false
        virtual bool AddFrontCurve(OwnerPtr<ICurve2d> opCurve) = 0;

        /// \brief  在多段线的末尾添加曲线
        /// 
        /// \param opCurve    二维曲线，非闭合并且与多段线末尾曲线相连，否则添加失败
        /// \return  成功添加返回True，否则返回false
        virtual bool AddBackCurve(OwnerPtr<ICurve2d> opCurve) = 0;

        /// \brief 删除多段线的首段曲线
        /// 
        /// \return 删除成功返回true，删除失败返回false。
        virtual bool DeleteFrontCurve() = 0;

        /// \brief 删除多段线最后一段曲线
        /// 
        /// \return 删除成功返回true，删除失败返回false。
        virtual bool DeleteBackCurve() = 0;

        /// \brief 在多段线的起始和终止位置[startIndex, endIndex]之间替换曲线
        /// 
        /// \param startIndex    替换的起始位置，需要大于或等于0，小于多段线曲线数目
        /// \param endIndex      替换的终止位置，需要大于或等于startIndex，小于多段线曲线数目
        /// \param opCurve2d     待替换的曲线，需要非闭合并且与多段线待替换的起始终止位置曲线相连，否则替换失败
        /// \return 替换成功返回True，否则返回false
        virtual bool ReplaceCurve(int startIndex, int endIndex, OwnerPtr<ICurve2d> opCurve2d) = 0;

        /// \brief 在多段线的起始和终止位置[startIndex, endIndex]之间替换曲线
        /// 
        /// \param startIndex      替换的起始位置，需要大于或等于0，小于多段线曲线数目
        /// \param endIndex        替换的终止位置，需要大于startIndex或等于，小于多段线曲线数目
        /// \param opIPolyCurve    多段线（二维），不能没有几何数据（即使用IPolyCurve::Create()直接创建），
        ///                        并且需要与待替换的起始、终止位置曲线相连,否则替换失败
        /// \return  替换曲线且合法返回True，否则返回false
        virtual bool ReplaceCurve(int startIndex, int endIndex, OwnerPtr<IPolyCurve> opPolyCurve) = 0;

        /// \brief  将多段线的某个位置的曲线替换为多段线
        /// 
        /// \param index            替换的位置，需要大于或等于0，小于多段线曲线数目
        /// \param opPolyCurve      待替换的多段线几何数据，不能没有几何数据（即使用IPolyCurve::Create()直接创建），
        ///                         并且其起点和终点需要与待替换位置曲线的起点终点一致，否则替换失败
        /// \return  替换成功返回True，否则返回false
        virtual bool ReplaceCurve(int index, OwnerPtr<IPolyCurve> opPolyCurve) = 0;

        /// \brief  设置是否启用线型生成
        /// 
        /// \param isTypeGenEnable true表示启用线型生成，false表示禁用线型生成
        /// \return 返回true表示设置成功，false表示设置失败
        virtual bool SetIsEnableLinetypeGeneration(bool isTypeGenEnable) = 0;

        /// \brief  是否启用线型生成
        /// 
        /// \return 返回true表示启用线型生成，false表示禁用线型生成
        virtual bool IsEnableLinetypeGeneration() const = 0;

        /// \brief  获取多段线整体线宽值
        /// 
        /// 获取的线宽值是多段线线宽属性值，并非多段线的样式线宽，其显示效果不受线宽显示开关的影响
        /// \return 多段线整体的线宽值
        virtual double GetLineWidth() const = 0;

        /// \brief  设置多段线整体线宽值
        /// 
        /// 设置的线宽值作为多段线的一个属性，并非多段线的样式线宽值，其显示效果不受线宽显示开关的影响
        /// 若设置的线宽值为0或者处于定像素模式下，那么多段线显示的线宽与样式线宽值保持一致,显示效果会受线宽显示开关影响
        /// \param  lineWidth      线宽值
        /// \return 设置成功返回true,否则返回false
        virtual bool SetLineWidth(double lineWidth) = 0;

        /// \brief  设置多段线某一段的线宽值
        /// 
        /// 设置的线宽值作为多段线的一个属性，并非多段线的样式线宽值，其显示效果不受线宽显示开关的影响
        /// 若设置的线宽值为0或者处于定像素模式下，那么多段线显示的线宽与样式线宽值保持一致,显示效果会受线宽显示开关影响
        /// 多段线每一段均有各自的起点线宽和终点线宽，并且两个线宽值可以不同；线宽值不同时，多段线产生渐变效果
        /// 使用SetLineWidth修改多段线的整体宽度属性时，其中的每段线段起点宽度与终点宽度均设置为整体宽度相同的值
        /// \param  curveIndex      多段线内部某一段的索引值
        /// \param  startWidth      起点线宽值
        /// \param  endWidth        终点线宽值
        /// \return 设置成功返回true,否则返回false
        virtual bool SetSegmentLineWidth(int curveIndex, double startWidth, double endWidth) = 0;

        /// \brief  获取多段线内部某一段的线宽值
        /// 
        /// 获取的线宽值是多段线线宽属性值，并非多段线的样式线宽，其显示效果不受线宽显示开关的影响
        /// \param  curveIndex      多段线内部某一段的索引值
        /// \return 返回多段线内部某一段的起点和终点线宽值，std::pair<double,double>分别对应起点和终点线宽
        virtual std::pair<double, double> GetSegmentLineWidth(int curveIndex) const = 0;

        /// \brief  按照索引顺序获取多段线内部每一段曲线的稳定标识
        /// 
        /// 多段线内部某条曲线由于增删改行为，使得曲线数目发生变化时，新生成曲线的标识会重新生成；未发生变化的曲线其稳定标识不会发生变化。
        /// \return 返回多段线内部每段曲线的唯一稳定标识
        virtual std::vector<Int32> GetAllStableCurveIds() const = 0;

        /// \brief 设置是否闭合
        ///
        /// \param isClosed 是否闭合
        /// \return 返回true表示设置成功，否则设置失败
        virtual bool SetIsClosed(bool isClosed) = 0;

        /// \brief 是否闭合
        ///
        /// \return 返回true表示闭合，否则不闭合
        virtual bool IsClosed() const = 0;

        /// \brief 设置是否可以被选择
        /// 
        /// \param isSelectable true-可以被选择；false-不可以被选择
        /// \return true 设置成功，false设置失败
        virtual bool SetIsSelectable(bool isSelectable) = 0;

        /// \brief 获取是否可以被选择
        /// 
        /// \return true-可以被选择；false-不可以被选择
        virtual bool IsSelectable() const = 0;

        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();

        /// \brief 获取多段线几何数据关联更新变化Id
        ///
        /// \return 多段线几何数据关联更新变化Id
        virtual RegenDataId GetGeometryChangedRdId() const = 0;

    public:
        /// \brief  创建二维多段线
        /// 
        /// \param pDocument 文档指针
        /// \param pModelView 所属的ModelView
        /// \param opPolyCurve 多段线几何数据
        /// \param eco 元素创建选项，默认为normal
        /// \return 设置成功返回true,否则返回false 
        static IDrawingPolyCurve* Create(gcmp::IDocument * pDocument, const IModelView* pModelView, OwnerPtr<IPolyCurve> opPolyCurve, ElementCreationOptions eco = ElementCreationOptions::Normal);

        /// \brief 获取多段线变化通知事件
        ///
        /// \return 返回获取多段线变化通知事件
        static IDrawingPolyCurveEvent* GetDrawingPolyCurveEvent();
    };
}
